package org.os.framework.context.config;

import org.os.framework.context.model.RejectedExecutionHandlers;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 线程池
 * 
 * @author weizuxiao
 */
@Slf4j
@Data
@ConfigurationProperties(prefix = "spring.thread-pool")
@Configuration
public class ThreadPoolConfig {

    /**
     * 核心线程数
     */
    private Integer corePoolSize = Runtime.getRuntime().availableProcessors();

    /**
     * 最大线程数
     */
    private Integer maxPoolSize = Runtime.getRuntime().availableProcessors() * 2;

    /**
     * 队列容量
     */
    private Integer queueCapacity = Runtime.getRuntime().availableProcessors() * 4;

    /**
     * 空闲线程的保持时间（秒）
     */
    private Integer keepAliveSeconds = 30;

    /**
     * 线程名称前缀
     */
    private String threadNamePrefix = "thread-pool-";

    /**
     * 是否等待任务完成才关闭线程池
     */
    private Boolean waitForTasksToCompleteOnShutdown = true;

    /**
     * 线程池关闭时等待任务结束的最长时间（秒）
     */
    private Integer awaitTerminationSeconds = 30;

    /**
     * 拒绝策略
     */
    private RejectedExecutionHandlers rejectedExecutionHandler = RejectedExecutionHandlers.Abort;

    @Bean(name = "threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        log.info("已启用线程池配置：{}", this);
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setThreadNamePrefix(threadNamePrefix);
        executor.setWaitForTasksToCompleteOnShutdown(waitForTasksToCompleteOnShutdown);
        executor.setAwaitTerminationSeconds(awaitTerminationSeconds);
        executor.setRejectedExecutionHandler(rejectedExecutionHandler.getRejectedExecutionHandler());
        executor.initialize();
        return executor;
    }

}
